package com.lab.account.service;

import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.common.dao.GenericDao;
import com.common.service.GenericManagerImpl;
import com.common.service.NoSuchUserException;
import com.common.service.ServiceException;
import com.lab.account.domain.Role;
import com.lab.account.domain.User;

@Service(value = "userManager")
public class UserManagerImpl extends GenericManagerImpl<User, Long> implements
        UserManager, UserDetailsService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private GenericDao<User, Long> userDao;
    @Autowired
    private RoleManager roleManager;

    @Autowired
    public UserManagerImpl(@Qualifier("userDao")
    GenericDao<User, Long> userDao) {
        super(userDao);
        this.userDao = userDao;
    }

    public void init() throws Exception {
    /*DetachedCriteria dc = DetachedCriteria.forClass(User.class);
    dc.add(Restrictions.eq("username", "hahah"));
    userDao.findByCriteria(dc);*/
    }

    public User login(User user) throws NoSuchUserException {
        DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
        criteria.add(Restrictions.eq("username", user.getUsername()));
        criteria.add(Restrictions.eq("password", user.getPassword()));

        List<User> list = userDao.findByCriteria(criteria);
        if (list.isEmpty()) {
            throw new NoSuchUserException();
        } else {
            return list.get(0);
        }
    }

    @Override
    public User save(User user) throws ServiceException {
        String md5Password = DigestUtils.md5Hex(user.getPassword());
        try {
            logger.info("save a user in update mode.");

            User dbUser = getByUsername(user.getUsername());
            if (!user.getPassword().equals(dbUser.getPassword())) {
                user.setPassword(md5Password);
            }
        } catch (UsernameNotFoundException e) {
            logger.info("save a user in creation mode.");

            user.setPassword(md5Password);

            return super.save(user);
        }

        return super.save(user);
    }

    public User getByUsername(String username) throws UsernameNotFoundException {
        return (User) loadUserByUsername(username);
    }

    public boolean isUsernameUnique(String newUsername, String oldUsername) {
        return userDao.isPropertyUnique("username", newUsername, oldUsername);
    }

    public List<Role> getRoleList() throws ServiceException {
        return roleManager.getAll();
    }

    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        DetachedCriteria dc = DetachedCriteria.forClass(User.class);
        dc.add(Restrictions.eq("username", username));

        List<User> list = userDao.findByCriteria(dc);
        if (list.isEmpty()) {
            throw new UsernameNotFoundException("User: " + username
                    + " does not exist.");
        }

        return list.get(0);
    }

    public List<User> getByPassword(String password) throws NoSuchUserException {
        DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
        criteria.add(Restrictions.eq("password", password));

        List<User> list = userDao.findByCriteria(criteria);
        if (list.isEmpty()) {
            throw new NoSuchUserException();
        } else {
            return list;
        }
    }
}
